home *** CD-ROM | disk | FTP | other *** search
Text File | 2000-06-23 | 34.2 KB | 1,230 lines |
- //////////
- //
- // File: VRMovies.c
- //
- // Contains: Support for QuickTime movie playback in VR nodes.
- //
- // Written by: Tim Monroe
- // Some code borrowed from QTVRSamplePlayer by Bryce Wolfson.
- //
- // Copyright: © 1996-1998 by Apple Computer, Inc., all rights reserved.
- //
- // Change History (most recent first):
- //
- // <15> 06/23/99 rtm added VRMoov_MacRGBToWinRGB and VRMoov_WinRGBToMacRGB
- // <14> 06/22/99 rtm more work on matrices; now everything works okay (AFAICT)
- // <13> 06/21/99 rtm added call to UpdateMovie to back buffer imaging procedure
- // <12> 06/18/99 rtm got movie matrices working correctly; added color picking to Windows
- // <11> 06/17/99 rtm reworked geometry of back buffer yet again; now we copy from the
- // offscreen GWorld to back buffer using use DecompressSequenceFrameS
- // <10> 05/16/99 rtm added VRMoov_DumpWindowData; further work on geometry of back buffer
- // <9> 05/15/99 rtm reworked geometry handling to support horizontal back buffer in QT 4.0
- // <8> 05/04/98 rtm added automatic rotation of movie
- // <7> 03/06/97 rtm started to implement video masking
- // <6> 03/05/97 rtm added VRMoov_SetChromaColor; added fChromaColor to app data record
- // <5> 03/04/97 rtm fixed compositing problems at back buffer edges
- // <4> 03/03/97 rtm added VRMoov_SetVideoGraphicsMode to handle compositing
- // without using an offscreen GWorld
- // <3> 02/27/97 rtm further development: borrowed some ideas from QTVRSamplePlayer;
- // added VRMoov_SetEmbeddedMovieWidth etc.
- // <2> 12/12/96 rtm further development: borrowed some ideas from BoxMoov demo
- // <1> 12/11/96 rtm first file
- //
- // This code draws the QuickTime movie frames into the back buffer, either directly
- // or indirectly (via an offscreen GWorld). Direct drawing gives the best performance,
- // but indirect drawing is necessary for some visual effects.
- //
- //////////
-
- // TO DO:
- // + finish video masking by custom 'hide' hot spots (so video goes *behind* such hot spots)
- // + verify that everything works okay if *images* are used instead of movies (scaling seems to be a problem)
-
-
- //////////
- //
- // header files
- //
- //////////
-
- #include "VRMovies.h"
-
-
- //////////
- //
- // constants
- //
- //////////
-
- const RGBColor kClearColor = {0x0000, 0xffff, 0x0000}; // the default chroma key color
- const RGBColor kBlackColor = {0x0000, 0x0000, 0x0000};
- const RGBColor kWhiteColor = {0xffff, 0xffff, 0xffff};
-
-
- //////////
- //
- // global variables
- //
- //////////
-
- #if TARGET_OS_MAC
- UserEventUPP gColorFilterUPP = NULL; // UPP to our custom color picker dialog event filter
- #endif
-
-
- //////////
- //
- // VRMoov_InitWindowData
- // Initialize any window-specific data.
- //
- //////////
-
- ApplicationDataHdl VRMoov_InitWindowData (WindowObject theWindowObject)
- {
- #pragma unused(theWindowObject)
-
- ApplicationDataHdl myAppData;
-
- myAppData = (ApplicationDataHdl)NewHandleClear(sizeof(ApplicationDataRecord));
- if (myAppData != NULL) {
- (**myAppData).fMovie = NULL;
- (**myAppData).fOffscreenGWorld = NULL;
- (**myAppData).fOffscreenPixMap = NULL;
- (**myAppData).fPrevBBufGWorld = NULL;
- (**myAppData).fMovieCenter.x = 0.0;
- (**myAppData).fMovieCenter.y = 0.0;
- (**myAppData).fMovieScale = 1.0;
- (**myAppData).fMovieWidth = kDefaultEmbMovieWidth;
- (**myAppData).fUseOffscreenGWorld = false;
- (**myAppData).fUseMovieCenter = true;
- (**myAppData).fQTMovieHasSound = false;
- (**myAppData).fCompositeMovie = false;
- (**myAppData).fUseHideRegion = false;
- (**myAppData).fChromaColor = kClearColor;
- (**myAppData).fHideRegion = NULL;
- (**myAppData).fBackBufferIsHoriz = false;
- (**myAppData).fImageDesc = NULL;
- (**myAppData).fImageSequence = 0;
-
- SetIdentityMatrix(&(**myAppData).fMovieMatrix);
- SetIdentityMatrix(&(**myAppData).fOrigMovieMatrix);
-
- // create a new routine descriptor
- (**myAppData).fBackBufferProc = NewQTVRBackBufferImagingProc(VRMoov_BackBufferImagingProc);
- }
-
- #if TARGET_OS_MAC
- if (gColorFilterUPP == NULL)
- gColorFilterUPP = NewUserEventProc(VRMoov_ColorDialogEventFilter);
- #endif
-
- return(myAppData);
- }
-
-
- //////////
- //
- // VRMoov_DumpWindowData
- // Dispose of any window-specific data.
- //
- //////////
-
- void VRMoov_DumpWindowData (WindowObject theWindowObject)
- {
- ApplicationDataHdl myAppData = NULL;
-
- myAppData = (ApplicationDataHdl)GetAppDataFromWindowObject(theWindowObject);
- if (myAppData == NULL)
- return;
-
- VRMoov_DumpEmbeddedMovie(theWindowObject);
-
- DisposeRoutineDescriptor((**myAppData).fBackBufferProc);
- }
-
-
- ///////////
- //
- // VRMoov_GetEmbeddedMovie
- // Get the QuickTime movie to be embedded in a panorama.
- // Returns a Boolean to indicate success (true) or failure (false).
- //
- //////////
-
- Boolean VRMoov_GetEmbeddedMovie (WindowObject theWindowObject)
- {
- StandardFileReply myReply;
- short myNumTypes = 1;
- SFTypeList myTypes = {MovieFileType, 0};
-
- // do some preliminary parameter checking
- if (theWindowObject == NULL)
- return(false);
-
- if (!IsWindowObjectOurs(theWindowObject))
- return(false);
-
- // elicit the movie file from user
- StandardGetFilePreview(NULL, myNumTypes, myTypes, &myReply);
- if (!myReply.sfGood) {
- VRMoov_DumpEmbeddedMovie(theWindowObject); // clean up any existing embedded movie
- return(false);
- }
-
- return(VRMoov_LoadEmbeddedMovie(&myReply.sfFile, theWindowObject));
- }
-
-
- //////////
- //
- // VRMoov_LoadEmbeddedMovie
- // Load the QuickTime movie in the specified file.
- // Returns a Boolean to indicate success (true) or failure (false).
- //
- //////////
-
- Boolean VRMoov_LoadEmbeddedMovie (FSSpec *theMovieFile, WindowObject theWindowObject)
- {
- short myMovieFileRef;
- Movie myMovie;
- GWorldPtr myGWorld = NULL;
- Rect myRect;
- ApplicationDataHdl myAppData = NULL;
- OSErr myErr = paramErr;
-
- myAppData = (ApplicationDataHdl)GetAppDataFromWindowObject(theWindowObject);
- if (myAppData == NULL)
- goto bail;
-
- HLock((Handle)myAppData);
-
- //////////
- //
- // open the movie file and the movie
- //
- //////////
-
- myErr = OpenMovieFile(theMovieFile, &myMovieFileRef, fsRdPerm);
- if (myErr != noErr)
- goto bail;
-
- myErr = NewMovieFromFile(&myMovie, myMovieFileRef, NULL, (StringPtr)NULL, newMovieActive, NULL);
- if (myErr != noErr)
- goto bail;
-
- //////////
- //
- // get the movie geometry
- //
- //////////
-
- GetMovieBox(myMovie, &myRect);
- GetMovieMatrix(myMovie, &(**myAppData).fOrigMovieMatrix);
- MacOffsetRect(&myRect, -myRect.left, -myRect.top);
- SetMovieBox(myMovie, &myRect);
-
- // keep track of the movie and movie rectangle (in our app-specific data structure)
- (**myAppData).fMovie = myMovie;
- (**myAppData).fMovieBox = myRect;
-
- // determine the orientation of the back buffer
- (**myAppData).fBackBufferIsHoriz = QTVRUtils_IsBackBufferHorizontal((**theWindowObject).fInstance);
-
- // get rid of any existing offscreen graphics world
- if ((**myAppData).fOffscreenGWorld != NULL) {
- DisposeGWorld((**myAppData).fOffscreenGWorld);
- (**myAppData).fOffscreenGWorld = NULL;
- }
-
- // clear out any existing custom cover/uncover functions and reset the video media graphics mode
- // (these may have been modified for direct-screen drawing)
- SetMovieCoverProcs(myMovie, NULL, NULL, 0L);
- VRMoov_SetVideoGraphicsMode(myMovie, myAppData, false);
-
- //////////
- //
- // if necessary, create an offscreen graphics world
- //
- // this is where we'll image the movie before copying it into the back buffer
- // when we want to do special effects
- //
- //////////
-
- if ((**myAppData).fUseOffscreenGWorld) {
- myErr = NewGWorld(&myGWorld, 0, &myRect, NULL, NULL, 0);
- (**myAppData).fOffscreenGWorld = myGWorld;
- (**myAppData).fOffscreenPixMap = GetGWorldPixMap(myGWorld);
-
- // make an image description, which is needed by DecompressSequenceBegin
- LockPixels((**myAppData).fOffscreenPixMap);
- MakeImageDescriptionForPixMap((**myAppData).fOffscreenPixMap, &((**myAppData).fImageDesc));
- UnlockPixels((**myAppData).fOffscreenPixMap);
- } else {
- // set the video media graphics mode to drop out the chroma key color in a movie;
- // we also need to install an uncover function that doesn't erase the uncovered region
- if ((**myAppData).fCompositeMovie) {
- VRMoov_SetVideoGraphicsMode(myMovie, myAppData, true);
- SetMovieCoverProcs(myMovie, NewMovieRgnCoverProc(VRMoov_UncoverProc), NULL, (long)theWindowObject);
- }
- }
-
- //////////
- //
- // install the back-buffer imaging procedure
- //
- //////////
-
- if ((**theWindowObject).fInstance != NULL)
- myErr = VRMoov_InstallBackBufferImagingProc((**theWindowObject).fInstance, theWindowObject);
-
- // start the movie playing in a loop
- VRMoov_LoopEmbeddedMovie(myMovie);
-
- bail:
- // we don't want to edit the embedded movie, so we can close the movie file
- if (myMovieFileRef != 0)
- CloseMovieFile(myMovieFileRef);
-
- HUnlock((Handle)myAppData);
-
- return(myErr == noErr);
- }
-
-
- //////////
- //
- // VRMoov_LoopEmbeddedMovie
- // Start the QuickTime movie playing in a loop.
- //
- //////////
-
- void VRMoov_LoopEmbeddedMovie (Movie theMovie)
- {
- TimeBase myTimeBase;
-
- // throw the movie into loop mode
- myTimeBase = GetMovieTimeBase(theMovie);
- SetTimeBaseFlags(myTimeBase, GetTimeBaseFlags(myTimeBase) | loopTimeBase);
-
- // start playing the movie
- StartMovie(theMovie);
- }
-
-
- //////////
- //
- // VRMoov_DumpEmbeddedMovie
- // Stop any existing embedded movie from playing and then clean up.
- //
- //////////
-
- void VRMoov_DumpEmbeddedMovie (WindowObject theWindowObject)
- {
- ApplicationDataHdl myAppData;
-
- if (theWindowObject == NULL)
- goto bail;
-
- myAppData = (ApplicationDataHdl)GetAppDataFromWindowObject(theWindowObject);
- if (myAppData == NULL)
- goto bail;
-
- // if we have an embedded movie, stop it from playing and dispose of it
- if ((**myAppData).fMovie != NULL) {
- StopMovie((**myAppData).fMovie);
- DisposeMovie((**myAppData).fMovie);
- (**myAppData).fMovie = NULL;
- }
-
- // get rid of any existing offscreen graphics world
- if ((**myAppData).fOffscreenGWorld != NULL) {
- DisposeGWorld((**myAppData).fOffscreenGWorld);
- (**myAppData).fOffscreenGWorld = NULL;
- }
-
- // clear the existing back buffer imaging proc
- QTVRSetBackBufferImagingProc((**theWindowObject).fInstance, NULL, 0, NULL, 0);
-
- // clear out any other movie-specific data
- (**myAppData).fPrevBBufGWorld = NULL;
- MacSetRect(&(**myAppData).fPrevBBufRect, 0, 0, 0, 0);
-
- MacSetRect(&(**myAppData).fMovieBox, 0, 0, 0, 0);
- SetIdentityMatrix(&(**myAppData).fMovieMatrix);
- SetIdentityMatrix(&(**myAppData).fOrigMovieMatrix);
-
- if ((**myAppData).fImageDesc != NULL) {
- DisposeHandle((Handle)(**myAppData).fImageDesc);
- (**myAppData).fImageDesc = NULL;
- }
-
- VRMoov_RemoveDecompSeq(theWindowObject);
-
- // make sure the back buffer is clean
- QTVRRefreshBackBuffer((**theWindowObject).fInstance, 0);
-
- bail:
- return;
- }
-
-
- //////////
- //
- // VRMoov_InstallBackBufferImagingProc
- // Install a back buffer imaging procedure.
- // (This routine might sometimes be called to move or resize the area of interest within the panorama.)
- //
- //////////
-
- OSErr VRMoov_InstallBackBufferImagingProc (QTVRInstance theInstance, WindowObject theWindowObject)
- {
- ApplicationDataHdl myAppData;
- QTVRAreaOfInterest myArea;
- float myWidth, myHeight;
- OSErr myErr = noErr;
-
- //////////
- //
- // initialize; clean up any existing back buffer procedure
- //
- //////////
-
- if ((theInstance == NULL) || (theWindowObject == NULL))
- return(paramErr);
-
- myAppData = (ApplicationDataHdl)GetAppDataFromWindowObject(theWindowObject);
- if (myAppData == NULL)
- return(paramErr);
-
- HLock((Handle)myAppData);
-
- // remove any existing back buffer imaging procedure
- if ((**myAppData).fBackBufferProc != NULL)
- QTVRSetBackBufferImagingProc(theInstance, NULL, 0, NULL, 0);
-
- //////////
- //
- // set the area of interest
- //
- // the panAngle and tiltAngle fields define the top-left corner, in panorama space, of the area of interest;
- // so here we do not have to worry about whether the back buffer is oriented vertically or horizontally
- //
- //////////
-
- // the application data structure holds the desired width, center, size, and scale of the movie
- myWidth = (**myAppData).fMovieWidth * (**myAppData).fMovieScale;
- myHeight = myWidth * (((float)(**myAppData).fMovieBox.bottom) / ((float)(**myAppData).fMovieBox.right));
-
- if ((**myAppData).fUseMovieCenter) {
- // use the stored movie center
- myArea.panAngle = (**myAppData).fMovieCenter.x + (myWidth/2);
- myArea.tiltAngle = (**myAppData).fMovieCenter.y + (myHeight/2);
- } else {
- // center the movie on the current pan and tilt angles
- myArea.panAngle = QTVRGetPanAngle(theInstance) + (myWidth/2);
- myArea.tiltAngle = QTVRGetTiltAngle(theInstance) + (myHeight/2);
- }
-
- myArea.width = myWidth;
- myArea.height = myHeight;
-
- //////////
- //
- // set the back buffer flags and install the back buffer procedure
- //
- //////////
-
- // make sure we get called on every idle event, so we can keep playing the embedded movie;
- // also make sure we get called on every back buffer update
- if ((**myAppData).fCompositeMovie)
- myArea.flags = kQTVRBackBufferEveryIdle | kQTVRBackBufferEveryUpdate | kQTVRBackBufferAlwaysRefresh;
- else
- myArea.flags = kQTVRBackBufferEveryIdle | kQTVRBackBufferEveryUpdate;
-
- // if the back buffer is oriented horizontally, set the appropriate flag
- if ((**myAppData).fBackBufferIsHoriz)
- myArea.flags |= kQTVRBackBufferHorizontal;
-
- // install our procedure
- myErr = QTVRSetBackBufferImagingProc(theInstance, (**myAppData).fBackBufferProc, 1, &myArea, (SInt32)theWindowObject);
-
- HUnlock((Handle)myAppData);
- return(myErr);
- }
-
-
- //////////
- //
- // VRMoov_CalcImagingMatrix
- // Calculate the movie matrix required to draw the embedded movie into the specified rectangle.
- //
- //////////
-
- OSErr VRMoov_CalcImagingMatrix (WindowObject theWindowObject, Rect *theBBufRect)
- {
- ApplicationDataHdl myAppData = NULL;
- Rect myDestRect = *theBBufRect;
-
- myAppData = (ApplicationDataHdl)GetAppDataFromWindowObject(theWindowObject);
- if (myAppData == NULL)
- return(paramErr);
-
- // reset the current movie matrix with the original movie matrix of the embedded movie;
- // we need to preserve that matrix in our calculations below if we are not drawing the
- // movie into an offscreen GWorld
- (**myAppData).fMovieMatrix = (**myAppData).fOrigMovieMatrix;
-
- // in general, it's easiest to construct the desired matrix by first doing the scaling
- // and then doing the rotation and translation (if necessary); so we need to swap the
- // right and bottom edges of the back buffer rectangle before doing the scaling, if a
- // rotation will also be necessary
- if (!(**myAppData).fBackBufferIsHoriz) {
- myDestRect.bottom = theBBufRect->right;
- myDestRect.right = theBBufRect->bottom;
- }
-
- // set up the scaling matrix
- // (MapMatrix concatenates the new matrix to the existing matrix, whereas RectMatrix first
- // sets the existing matrix to the identity matrix)
- if ((**myAppData).fUseOffscreenGWorld)
- RectMatrix(&(**myAppData).fMovieMatrix, &(**myAppData).fMovieBox, &myDestRect);
- else
- MapMatrix(&(**myAppData).fMovieMatrix, &(**myAppData).fMovieBox, &myDestRect);
-
- // add a rotation and translation, if necessary
- if (!(**myAppData).fBackBufferIsHoriz) {
- RotateMatrix(&(**myAppData).fMovieMatrix, Long2Fix(-90), 0, 0);
- TranslateMatrix(&(**myAppData).fMovieMatrix, 0, Long2Fix(RECT_HEIGHT(*theBBufRect)));
- }
-
- // Delay(1, NULL); // TESTING TESTING
-
- return(noErr);
- }
-
-
- //////////
- //
- // VRMoov_SetupDecompSeq
- // Set up the decompression sequence for DecompressionSequenceFrameS.
- //
- // This needs to be called whenever either the rectangle or the GWorld of the back buffer changes.
- //
- //////////
-
- OSErr VRMoov_SetupDecompSeq (WindowObject theWindowObject, GWorldPtr theDestGWorld)
- {
- ApplicationDataHdl myAppData = NULL;
- short myMode = srcCopy;
- OSErr myErr = noErr;
-
- myAppData = (ApplicationDataHdl)GetAppDataFromWindowObject(theWindowObject);
- if (myAppData == NULL)
- return(paramErr);
-
- // make sure we don't have a decompression sequence already open
- VRMoov_RemoveDecompSeq(theWindowObject);
-
- // set up the transfer mode
- if ((**myAppData).fCompositeMovie)
- myMode = srcCopy | transparent;
-
- // set up the image decompression sequence
- myErr = DecompressSequenceBegin( &(**myAppData).fImageSequence,
- (**myAppData).fImageDesc,
- (CGrafPtr)theDestGWorld,
- NULL,
- NULL, // entire source image
- &(**myAppData).fMovieMatrix,
- myMode,
- NULL, // no mask
- 0,
- (**(**myAppData).fImageDesc).spatialQuality,
- NULL);
-
- return(myErr);
- }
-
-
- //////////
- //
- // VRMoov_RemoveDecompSeq
- // Remove the decompression sequence for DecompressionSequenceFrameS.
- //
- //////////
-
- OSErr VRMoov_RemoveDecompSeq (WindowObject theWindowObject)
- {
- ApplicationDataHdl myAppData = NULL;
- OSErr myErr = paramErr;
-
- if (theWindowObject != NULL) {
- myAppData = (ApplicationDataHdl)GetAppDataFromWindowObject(theWindowObject);
- if (myAppData != NULL)
- if ((**myAppData).fImageSequence != 0) {
- myErr = CDSequenceEnd((**myAppData).fImageSequence);
- (**myAppData).fImageSequence = 0;
- }
- }
-
- return(myErr);
- }
-
-
- //////////
- //
- // VRMoov_BackBufferImagingProc
- // The back buffer imaging procedure: get a frame of movie and image it into the back buffer.
- // Also, do any additional compositing that might be desired.
- //
- //////////
-
- PASCAL_RTN OSErr VRMoov_BackBufferImagingProc (QTVRInstance theInstance, Rect *theRect, UInt16 theAreaIndex, UInt32 theFlagsIn, UInt32 *theFlagsOut, WindowObject theWindowObject)
- {
- #pragma unused(theAreaIndex)
-
- ApplicationDataHdl myAppData = NULL;
- Movie myMovie = NULL;
- Boolean myIsDrawing = theFlagsIn & kQTVRBackBufferRectVisible;
- GWorldPtr myBBufGWorld, myMovGWorld;
- GDHandle myBBufGDevice, myMovGDevice;
- Rect myRect;
- OSErr myErr = paramErr;
-
- //////////
- //
- // initialize; make sure that we've got the data we need to continue
- //
- //////////
-
- // assume we're not going to draw anything
- *theFlagsOut = 0;
-
- if ((theInstance == NULL) || (theWindowObject == NULL))
- goto bail;
-
- myAppData = (ApplicationDataHdl)GetAppDataFromWindowObject(theWindowObject);
- if (myAppData == NULL)
- goto bail;
-
- HLock((Handle)myAppData);
-
- myMovie = (**myAppData).fMovie;
- if (myMovie == NULL) {
- // we don't have an embedded movie, so remove this back-buffer imaging procedure
- VRMoov_DumpEmbeddedMovie(theWindowObject);
- goto bail;
- }
-
- //////////
- //
- // make sure that the movie GWorld is set correctly;
- // note that we call SetMovieGWorld only if we have to (for performance reasons)
- //
- //////////
-
- // get the current graphics world
- // (on entry, the current graphics world is [usually] set to the back buffer)
- GetGWorld(&myBBufGWorld, &myBBufGDevice);
-
- // get the embedded movie's graphics world
- GetMovieGWorld(myMovie, &myMovGWorld, &myMovGDevice);
-
- if ((**myAppData).fUseOffscreenGWorld) {
- // we're using an offscreen graphics world, so set movie's GWorld to be that offscreen graphics world
- if (myMovGWorld != (**myAppData).fOffscreenGWorld)
- SetMovieGWorld(myMovie, (**myAppData).fOffscreenGWorld, GetGWorldDevice((**myAppData).fOffscreenGWorld));
- } else {
- // we're not using an offscreen graphics world, so set movie GWorld to be the back buffer;
- if ((myMovGWorld != myBBufGWorld) || (myMovGDevice != myBBufGDevice))
- SetMovieGWorld(myMovie, myBBufGWorld, myBBufGDevice);
- }
-
- //////////
- //
- // make sure the movie rectangle and movie matrix are set correctly
- //
- //////////
-
- if (myIsDrawing) {
- // if we weren't previously visible, make sure we are now
- GetMovieBox(myMovie, &myRect);
- if (EmptyRect(&myRect))
- SetMovieBox(myMovie, &(**myAppData).fMovieBox);
-
- // when no offscreen GWorld is being used...
- if (!(**myAppData).fUseOffscreenGWorld) {
-
- // ...make sure the movie matrix is set correctly...
- if (!MacEqualRect(theRect, &(**myAppData).fPrevBBufRect)) {
- VRMoov_CalcImagingMatrix(theWindowObject, theRect);
- SetMovieMatrix(myMovie, &(**myAppData).fMovieMatrix);
- }
-
- // ...and, if we are compositing, force QuickTime to draw a movie frame when MoviesTask is called
- // (since the previous frame was automatically erased from the back buffer by QuickTime VR)
- if ((**myAppData).fCompositeMovie)
- UpdateMovie(myMovie);
- }
-
- } else {
- // if we're not visible, set the movie rectangle to an empty rectangle
- // so we're not wasting time trying to draw a movie frame
- MacSetRect(&myRect, 0, 0, 0, 0);
- SetMovieBox(myMovie, &myRect);
- }
-
- //////////
- //
- // draw a new movie frame into the movie's graphics world (and play movie sound)
- //
- //////////
-
- MoviesTask(myMovie, 1L);
- // MoviesTask(myMovie, 0);
-
- // if we got here, everything is okay so far
- myErr = noErr;
-
- //////////
- //
- // perform any additional compositing
- //
- //////////
-
- // that is, draw, using the current chroma key color, anything to be dropped out of the image;
- // note that this technique works *only* if we're using an offscreen graphics world
- if ((**myAppData).fUseOffscreenGWorld && (**myAppData).fCompositeMovie && myIsDrawing) {
- RGBColor myColor;
-
- // since we're using an offscreen graphics world, make sure we draw there
- SetGWorld((**myAppData).fOffscreenGWorld, GetGWorldDevice((**myAppData).fOffscreenGWorld));
-
- // set up compositing environment
- GetForeColor(&myColor);
- RGBForeColor(&(**myAppData).fChromaColor);
-
- // do the drawing
- if ((**myAppData).fHideRegion != NULL)
- MacPaintRgn((**myAppData).fHideRegion);
-
- // restore original drawing environment
- RGBForeColor(&myColor);
-
- // restore original graphics world
- SetGWorld(myBBufGWorld, myBBufGDevice);
- }
-
- //////////
- //
- // if we're using an offscreen graphics world, copy it into the back buffer
- //
- //////////
-
- if (myIsDrawing) {
-
- if ((**myAppData).fUseOffscreenGWorld) {
- PixMapHandle myPixMap;
-
- // if anything relevant to DecompressSequenceFrameS has changed, reset the decompression sequence
- if ((myBBufGWorld != (**myAppData).fPrevBBufGWorld) || !(MacEqualRect(theRect, &(**myAppData).fPrevBBufRect))) {
- VRMoov_CalcImagingMatrix(theWindowObject, theRect);
- VRMoov_SetupDecompSeq(theWindowObject, myBBufGWorld);
- }
-
- myPixMap = GetGWorldPixMap((**myAppData).fOffscreenGWorld);
- LockPixels(myPixMap);
-
- // set the chroma key color, if necessary
- if ((**myAppData).fCompositeMovie)
- RGBBackColor(&(**myAppData).fChromaColor);
-
- // copy the image from the offscreen graphics world into the back buffer
- myErr = DecompressSequenceFrameS( (**myAppData).fImageSequence,
- StripAddress(GetPixBaseAddr(myPixMap)),
- (**(**myAppData).fImageDesc).dataSize,
- 0,
- NULL,
- NULL);
-
- // reset the chroma key color;
- // we need to do this because the buffer we just drew into might NOT actually
- // be the real back buffer (see Virtual Reality Programming With QuickTime VR, p. 1-154);
- // the copy between the intermediate buffer and the back buffer respects the current back color.
- if ((**myAppData).fCompositeMovie)
- RGBBackColor(&kWhiteColor);
-
- UnlockPixels(myPixMap);
- }
- }
-
- //////////
- //
- // finish up
- //
- //////////
-
- // keep track of the GWorld and rectangle passed to us this time
- (**myAppData).fPrevBBufGWorld = myBBufGWorld;
- (**myAppData).fPrevBBufRect = *theRect;
-
- // if we drew something, tell QuickTime VR
- if (myIsDrawing)
- *theFlagsOut = kQTVRBackBufferFlagDidDraw;
-
- bail:
- HUnlock((Handle)myAppData);
- return(myErr);
- }
-
-
- //////////
- //
- // VRMoov_GetEmbeddedMovieWidth
- // Get the width of the embedded movie.
- //
- //////////
-
- float VRMoov_GetEmbeddedMovieWidth (WindowObject theWindowObject)
- {
- ApplicationDataHdl myAppData;
- float myWidth;
-
- myAppData = (ApplicationDataHdl)GetAppDataFromWindowObject(theWindowObject);
- if (myAppData == NULL)
- myWidth = 0;
- else
- myWidth = (**myAppData).fMovieWidth;
-
- return(myWidth);
- }
-
-
- //////////
- //
- // VRMoov_SetEmbeddedMovieWidth
- // Set the width of the embedded movie.
- //
- //////////
-
- void VRMoov_SetEmbeddedMovieWidth (WindowObject theWindowObject, float theWidth)
- {
- ApplicationDataHdl myAppData;
- QTVRInstance myInstance;
-
- myAppData = (ApplicationDataHdl)GetAppDataFromWindowObject(theWindowObject);
- if (myAppData == NULL)
- return;
-
- myInstance = (**theWindowObject).fInstance;
- if (myInstance == NULL)
- return;
-
- // install the desired width in our application data structure
- (**myAppData).fMovieWidth = theWidth;
-
- // clear out the existing area of interest
- QTVRRefreshBackBuffer(myInstance, 0);
-
- // reinstall the back buffer imaging procedure
- VRMoov_InstallBackBufferImagingProc(myInstance, theWindowObject);
- }
-
-
- //////////
- //
- // VRMoov_GetEmbeddedMovieCenter
- // Get the center of the embedded movie.
- //
- //////////
-
- void VRMoov_GetEmbeddedMovieCenter (WindowObject theWindowObject, QTVRFloatPoint *theCenter)
- {
- ApplicationDataHdl myAppData;
-
- myAppData = (ApplicationDataHdl)GetAppDataFromWindowObject(theWindowObject);
- if (myAppData == NULL) {
- theCenter->x = 0.0;
- theCenter->y = 0.0;
- } else {
- theCenter->x = (**myAppData).fMovieCenter.x;
- theCenter->y = (**myAppData).fMovieCenter.y;
- }
-
- }
-
-
- //////////
- //
- // VRMoov_SetEmbeddedMovieCenter
- // Set the center of the embedded movie.
- //
- //////////
-
- void VRMoov_SetEmbeddedMovieCenter (WindowObject theWindowObject, const QTVRFloatPoint *theCenter)
- {
- ApplicationDataHdl myAppData;
- QTVRInstance myInstance;
- float myX, myY;
-
- myAppData = (ApplicationDataHdl)GetAppDataFromWindowObject(theWindowObject);
- if (myAppData == NULL)
- return;
-
- myInstance = (**theWindowObject).fInstance;
- if (myInstance == NULL)
- return;
-
- myX = theCenter->x;
- myY = theCenter->y;
-
- // subject the values passed in to the current view constraints
- QTVRWrapAndConstrain(myInstance, kQTVRPan, myX, &myX);
- QTVRWrapAndConstrain(myInstance, kQTVRTilt, myY, &myY);
-
- // install the desired center in our application data structure
- (**myAppData).fMovieCenter.x = myX;
- (**myAppData).fMovieCenter.y = myY;
-
- // clear out the existing area of interest
- QTVRRefreshBackBuffer(myInstance, 0);
-
- // reinstall the back buffer imaging procedure
- VRMoov_InstallBackBufferImagingProc(myInstance, theWindowObject);
- }
-
-
- //////////
- //
- // VRMoov_GetEmbeddedMovieScale
- // Get the scale of the embedded movie.
- //
- //////////
-
- float VRMoov_GetEmbeddedMovieScale (WindowObject theWindowObject)
- {
- ApplicationDataHdl myAppData;
- float myScale;
-
- myAppData = (ApplicationDataHdl)GetAppDataFromWindowObject(theWindowObject);
- if (myAppData == NULL)
- myScale = 0;
- else
- myScale = (**myAppData).fMovieScale;
-
- return(myScale);
- }
-
-
- //////////
- //
- // VRMoov_SetEmbeddedMovieScale
- // Set the scale factor of the embedded movie.
- //
- //////////
-
- void VRMoov_SetEmbeddedMovieScale (WindowObject theWindowObject, float theScale)
- {
- ApplicationDataHdl myAppData;
- QTVRInstance myInstance;
-
- myAppData = (ApplicationDataHdl)GetAppDataFromWindowObject(theWindowObject);
- if (myAppData == NULL)
- return;
-
- myInstance = (**theWindowObject).fInstance;
- if (myInstance == NULL)
- return;
-
- // install the desired scale factor in our application data structure
- (**myAppData).fMovieScale = theScale;
-
- // clear out the existing area of interest
- QTVRRefreshBackBuffer(myInstance, 0);
-
- // reinstall the back buffer imaging procedure
- VRMoov_InstallBackBufferImagingProc(myInstance, theWindowObject);
- }
-
-
- //////////
- //
- // VRMoov_SetChromaColor
- // Set the chroma key color for a window object:
- // display color picker dialog and remember the newly-selected color.
- //
- //////////
-
- void VRMoov_SetChromaColor (WindowObject theWindowObject)
- {
- #if TARGET_OS_MAC
- ColorPickerInfo myColorInfo;
- #endif
- #if TARGET_OS_WIN32
- static CHOOSECOLOR myColorRec;
- static COLORREF myColorRef[16];
- #endif
- ApplicationDataHdl myAppData;
-
- myAppData = (ApplicationDataHdl)GetAppDataFromWindowObject(theWindowObject);
- if (myAppData == NULL)
- return;
-
- #if TARGET_OS_MAC
- // pass in existing color
- myColorInfo.theColor.color.rgb.red = (**myAppData).fChromaColor.red;
- myColorInfo.theColor.color.rgb.green = (**myAppData).fChromaColor.green;
- myColorInfo.theColor.color.rgb.blue = (**myAppData).fChromaColor.blue;
-
- // not much here...
- myColorInfo.theColor.profile = 0L;
- myColorInfo.dstProfile = 0L;
- myColorInfo.flags = 0L;
- myColorInfo.placeWhere = kCenterOnMainScreen;
- myColorInfo.pickerType = 0L;
- myColorInfo.eventProc = gColorFilterUPP;
- myColorInfo.colorProc = NULL;
- myColorInfo.colorProcData = 0L;
- GetIndString(myColorInfo.prompt, kColorPickerTextStringID, 1);
-
- // set Edit menu info
- myColorInfo.mInfo.editMenuID = mEdit;
- myColorInfo.mInfo.undoItem = iUndo;
- myColorInfo.mInfo.cutItem = iCut;
- myColorInfo.mInfo.copyItem = iCopy;
- myColorInfo.mInfo.pasteItem = iPaste;
- myColorInfo.mInfo.clearItem = iClear;
-
- // call Color Picker
- if ((PickColor(&myColorInfo) == noErr) && (myColorInfo.newColorChosen)) {
- // install the newly chosen color in the palette
- (**myAppData).fChromaColor.red = myColorInfo.theColor.color.rgb.red;
- (**myAppData).fChromaColor.green = myColorInfo.theColor.color.rgb.green;
- (**myAppData).fChromaColor.blue = myColorInfo.theColor.color.rgb.blue;
- }
- #endif
- #if TARGET_OS_WIN32
- myColorRec.lStructSize = sizeof(CHOOSECOLOR);
- myColorRec.hwndOwner = NULL;
- myColorRec.hInstance = NULL;
-
- VRMoov_MacRGBToWinRGB(&(**myAppData).fChromaColor, &(myColorRec.rgbResult));
-
- myColorRec.lpCustColors = myColorRef;
- myColorRec.Flags = CC_RGBINIT | CC_FULLOPEN;
- myColorRec.lCustData = 0;
- myColorRec.lpfnHook = NULL;
- myColorRec.lpTemplateName = NULL;
-
- // call Common Color dialog
- if (ChooseColor(&myColorRec)) {
- // install the newly chosen color in the palette
- VRMoov_WinRGBToMacRGB(&(**myAppData).fChromaColor, myColorRec.rgbResult);
- }
- #endif
- }
-
-
- //////////
- //
- // VRMoov_ColorDialogEventFilter
- // Handle events before they get passed to the Color Picker dialog box.
- //
- //////////
-
- PASCAL_RTN Boolean VRMoov_ColorDialogEventFilter (EventRecord *theEvent)
- {
- #if TARGET_OS_WIN32
- #pragma unused(theEvent)
- #endif
- Boolean myEventHandled = false;
- OSErr myErr = noErr;
-
- #if TARGET_OS_MAC
- switch (theEvent->what) {
- case updateEvt: {
- if ((WindowPtr)theEvent->message != FrontWindow()) {
- DoUpdateWindow((WindowPtr)theEvent->message, &((WindowPtr)theEvent->message)->portRect);
- myEventHandled = true;
- }
- break;
- }
-
- case nullEvent: {
- // do idle-time processing for all open windows in our window list
- WindowObject myWindowObject = NULL;
- ApplicationDataHdl myAppData = NULL;
- WindowReference myWindow = NULL;
-
- myWindow = GetFrontMovieWindow();
- while (myWindow != NULL) {
- myWindowObject = (WindowObject)GetWindowObjectFromWindow(myWindow);
- myAppData = (ApplicationDataHdl)GetAppDataFromWindow(myWindow);
- if ((myWindowObject != NULL) && (myAppData != NULL))
- if ((**myAppData).fMovie != NULL)
- QTVRUpdate((**myWindowObject).fInstance, kQTVRCurrentMode);
- myWindow = GetNextMovieWindow(myWindow);
- }
-
- myEventHandled = false;
- break;
- }
-
- case kHighLevelEvent:
- myErr = AEProcessAppleEvent(theEvent);
- if (myErr != noErr)
- myEventHandled = true;
- break;
-
- default:
- myEventHandled = false;
- break;
- }
-
- #endif
- return(myEventHandled);
- }
-
-
- //////////
- //
- // VRMoov_UncoverProc
- // The uncover function of the embedded movie.
- //
- //////////
-
- PASCAL_RTN OSErr VRMoov_UncoverProc (Movie theMovie, RgnHandle theRegion, WindowObject theWindowObject)
- {
- #pragma unused(theMovie, theRegion, theWindowObject)
- return(noErr);
- }
-
-
- //////////
- //
- // VRMoov_SetVideoGraphicsMode
- // Set the video media graphics mode of the embedded movie.
- //
- //////////
-
- void VRMoov_SetVideoGraphicsMode (Movie theMovie, ApplicationDataHdl theAppData, Boolean theSetVGM)
- {
- long myTrackCount;
- short myIndex;
- Track myTrack = NULL;
- Media myMedia = NULL;
- OSType myMediaType;
-
- if ((theMovie == NULL) || (theAppData == NULL))
- return;
-
- myTrackCount = GetMovieTrackCount(theMovie);
- for (myIndex = 1; myIndex <= myTrackCount; myIndex++) {
- myTrack = GetMovieIndTrack(theMovie, myIndex);
- myMedia = GetTrackMedia(myTrack);
- GetMediaHandlerDescription(myMedia, &myMediaType, NULL, NULL);
- if (myMediaType == VideoMediaType) {
- if (theSetVGM)
- MediaSetGraphicsMode(GetMediaHandler(myMedia), srcCopy | transparent, &(**theAppData).fChromaColor);
- else
- MediaSetGraphicsMode(GetMediaHandler(myMedia), srcCopy, &kWhiteColor);
- }
- }
-
- return;
- }
-
-
- //////////
- //
- // VRMoov_GetVideoGraphicsPixelDepth
- // Return the highest pixel depth supported by a QuickTime movie.
- //
- //////////
-
- short VRMoov_GetVideoGraphicsPixelDepth (Movie theMovie)
- {
- long myTrackCount;
- short myIndex;
- Track myMovieTrack = NULL;
- Media myMedia;
- OSType myMediaType;
- short myQuality;
-
- myTrackCount = GetMovieTrackCount(theMovie);
- for (myIndex = 1; myIndex <= myTrackCount; myIndex++) {
- myMovieTrack = GetMovieIndTrack(theMovie, myIndex);
- myMedia = GetTrackMedia(myMovieTrack);
- GetMediaHandlerDescription(myMedia, &myMediaType, NULL, NULL);
- if (myMediaType == VideoMediaType) {
- myQuality = GetMediaQuality(myMedia);
- if (myQuality >> 5)
- return(32);
- if (myQuality >> 4)
- return(16);
- if (myQuality >> 3)
- return(8);
- if (myQuality >> 2)
- return(4);
- if (myQuality >> 1)
- return(2);
- if (myQuality >> 0)
- return(1);
- }
- }
-
- return(0);
- }
-
-
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////
- //
- // Color conversion utilities.
- //
- // Macintosh usually represents colors using an RGBColor structure, where each color component is a 16-bit
- // unsigned integer. Windows represents colors using a 32-bit unsigned COLORREF, where each color component
- // occupies 8 bits. The following two functions allow us to convert from Mac to Windows colors and back. We
- // need to do this because we use Mac-style colors when doing compositing.
- //
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////
-
- #if TARGET_OS_WIN32
-
- #define kMaxMacRGBValue 0xffff
- #define kMaxWinRGBValue 0x00ff
- #define MAC_TO_WIN_COMP(color) (color*((float)kMaxWinRGBValue/(float)kMaxMacRGBValue))
- #define WIN_TO_MAC_COMP(color) (color*((float)kMaxMacRGBValue/(float)kMaxWinRGBValue))
-
-
- //////////
- //
- // VRMoov_MacRGBToWinRGB
- // Convert an RGBColor structure into a COLORREF value.
- //
- //////////
-
- void VRMoov_MacRGBToWinRGB (RGBColorPtr theRGBColor, COLORREF *theColorRef)
- {
- *theColorRef = RGB( (BYTE)MAC_TO_WIN_COMP(theRGBColor->red),
- (BYTE)MAC_TO_WIN_COMP(theRGBColor->green),
- (BYTE)MAC_TO_WIN_COMP(theRGBColor->blue));
- }
-
-
- //////////
- //
- // VRMoov_WinRGBToMacRGB
- // Convert a COLORREF value into an RGBColor structure.
- //
- //////////
-
- void VRMoov_WinRGBToMacRGB (RGBColorPtr theRGBColor, COLORREF theColorRef)
- {
- theRGBColor->red = (unsigned long)WIN_TO_MAC_COMP(GetRValue(theColorRef));
- theRGBColor->green = (unsigned long)WIN_TO_MAC_COMP(GetGValue(theColorRef));
- theRGBColor->blue = (unsigned long)WIN_TO_MAC_COMP(GetBValue(theColorRef));
- }
- #endif // TARGET_OS_WIN32
-
-
-